#include <xmlsec/xmltree.h>
#include <string.h>

#include "mcx.h"

GTree *mcx_history(xmlSecKeyPtr key) {
  xmlDocPtr request, response;

  request = mcx_history_request(key);
  if(mcx_debug_get())
    xmlDocDump(stderr, request);
  response = mcx_send("AccountHistoryService", request);
  if(mcx_debug_get())
    xmlDocDump(stderr, response);
  return mcx_transactionList_parse(response);
}

struct mcx_transaction *mcx_transaction_parse(xmlNodePtr ptr) {
  struct mcx_transaction *ret;
  xmlNodePtr tmp;
  char *str, *end;

  if(!ptr || !xmlSecCheckNodeName(ptr, "transaction", ns_mcxws))
    return NULL;

  ret = calloc(1, sizeof(*ret));
  if(!ret)
    return NULL;
  if(

     (tmp = xmlSecFindChild(ptr, "time", ns_mcxws)) &&
     (ret->mt_time = strdup(xmlNodeGetContent(tmp))) &&

     (tmp = xmlSecFindChild(ptr, "amount", ns_mcx)) &&
     (ret->mt_amount = xmlNodeGetContent(tmp)) &&
     (ret->mt_currency = xmlGetProp(tmp, "currency")) &&

     (tmp = xmlSecFindChild(ptr, "authority", ns_mcxws)) &&
     (str = xmlNodeGetContent(tmp)) &&
     (ret->mt_authority = strtol(str, &end, 10)) &&
     !*end &&

     (tmp = xmlSecFindChild(ptr, "drawdown", ns_mcxws)) &&
     (str = xmlNodeGetContent(tmp)) &&
     (ret->mt_drawdown = strtol(str, &end, 10)) &&
     !*end

     ) {
    if(xmlSecFindChild(ptr, "debit", ns_mcxws)) {
      ret->mt_debit = 1;
      return ret;
    } else if(xmlSecFindChild(ptr, "credit", ns_mcxws))
      return ret;
  }
  free(ret);
  return NULL;
}

gint g_strcmp(gconstpointer a, gconstpointer b) {
  return strcmp(b, a);
}

GTree *mcx_transactionList_parse(xmlDocPtr doc) {
  GTree *ret = NULL;
  xmlNodePtr root, ptr;
  struct mcx_transaction *t;
  
  if(!doc || !(root = xmlDocGetRootElement(doc)) ||
     !xmlSecCheckNodeName(root, "transactionList", ns_mcxws))
    return NULL;
  ret = g_tree_new(g_strcmp);
  for(ptr = root->children; ptr; ptr = ptr->next)
    if(xmlSecCheckNodeName(ptr, "transaction", ns_mcxws) &&
       (t = mcx_transaction_parse(ptr))) {
      g_tree_insert(ret, t->mt_time, t);
    }
  return ret;
}

xmlDocPtr mcx_history_request(xmlSecKeyPtr key) {
  xmlDocPtr request;
  xmlNodePtr vi, root;

  request = mcx_doc_new(ns_mcxws, "mcxws", "accountHistoryRequest", NULL, &root);
  if(!request)
    return NULL;
  vi = mcx_validityInterval_offset(request, NULL, 0, 60);
  if(!vi)
    return NULL;		/* FIXME: memory leak */
  xmlAddChild(root, vi);
  if(!mcx_sign(root, key))
    return NULL;
  return request;
}
